from PySide6.QtCore import Slot, Qt, Signal
from PySide6.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout,
                               QLabel, QPushButton, QListWidget,
                               QTextEdit, QLineEdit, QGroupBox)
from PySide6.QtBluetooth import (QBluetoothDeviceInfo, QBluetoothSocket,QBluetoothAddress,
                                 QBluetoothServiceInfo, QBluetoothUuid)


class ChatPage(QWidget):
    r_data_singal = Signal(str)
    def __init__(self, discovery_agent, parent=None):
        super().__init__(parent)
        self.discovery = discovery_agent
        self.socket: QBluetoothSocket | None = None
        self._setup_ui()
        self.discovery.deviceDiscovered.connect(self._device_found)
        self.discovery.finished.connect(self._scan_finished)

    def _setup_ui(self):
        self.setStyleSheet('background:#e8f4f8;')
        lay = QVBoxLayout(self)

        # 标题
        lay.addWidget(QLabel('蓝牙功能', alignment=Qt.AlignCenter))

        # 控制条
        bar = QHBoxLayout()
        self.scan_btn = QPushButton('扫描设备')
        self.conn_btn = QPushButton('连接设备')
        self.disconn_btn = QPushButton('断开连接')
        self.conn_btn.setEnabled(False)
        self.disconn_btn.setEnabled(False)
        for b in (self.scan_btn, self.conn_btn, self.disconn_btn):
            bar.addWidget(b)
        lay.addLayout(bar)

        self.status_lbl = QLabel('蓝牙状态: 未连接')
        lay.addWidget(self.status_lbl)

        # 设备列表
        g1 = QGroupBox('发现设备')
        v1 = QVBoxLayout(g1)
        self.device_list = QListWidget()
        v1.addWidget(self.device_list)
        lay.addWidget(g1)

        # 数据通信
        g2 = QGroupBox('数据通信')
        v2 = QVBoxLayout(g2)
        self.data_edit = QTextEdit(readOnly=True)
        self.send_input = QLineEdit(placeholderText='输入要发送的数据...')
        self.send_input.setEnabled(False)
        self.send_btn = QPushButton('发送')
        self.send_btn.setEnabled(False)
        v2.addWidget(self.data_edit)
        h = QHBoxLayout()
        h.addWidget(self.send_input)
        h.addWidget(self.send_btn)
        v2.addLayout(h)
        lay.addWidget(g2)

        # 信号
        self.scan_btn.clicked.connect(self._start_scan)
        self.conn_btn.clicked.connect(self._connect)
        self.disconn_btn.clicked.connect(self._disconnect)
        self.send_btn.clicked.connect(self._send_data)
        self.device_list.itemSelectionChanged.connect(
            lambda: self.conn_btn.setEnabled(bool(self.device_list.currentItem())))

    # ---------- 槽 ----------
    @Slot()
    def _start_scan(self):
        self.device_list.clear()
        self.scan_btn.setEnabled(False)
        self.status_lbl.setText('蓝牙状态: 扫描中...')
        self.discovery.start()

    @Slot(QBluetoothDeviceInfo)
    def _device_found(self, info: QBluetoothDeviceInfo):
        txt = f'{info.address().toString()} - {info.name()}'
        self.device_list.addItem(txt)

    @Slot()
    def _scan_finished(self):
        self.scan_btn.setEnabled(True)
        c = self.device_list.count()
        self.status_lbl.setText(f'蓝牙状态: 扫描完成，发现 {c} 个设备')

    @Slot()
    def _connect(self):
        item = self.device_list.currentItem()
        if not item:
            return
        addr_str = item.text().split(' - ')[0]
        address = QBluetoothAddress(addr_str)
        # 断开旧连接
        if self.socket:
            self.socket.deleteLater()
        self.socket = QBluetoothSocket(QBluetoothServiceInfo.RfcommProtocol)
        self.socket.connected.connect(self._on_connected)
        self.socket.disconnected.connect(self._on_disconnected)
        self.socket.readyRead.connect(self._on_ready_read)
        self.socket.errorOccurred.connect(self._on_error)

        uuid = QBluetoothUuid(QBluetoothUuid.SerialPort)
        self.socket.connectToService(address, uuid)
        self.status_lbl.setText('蓝牙状态: 连接中...')

    @Slot()
    def _disconnect(self):
        if self.socket:
            self.socket.disconnectFromService()

    @Slot()
    def _send_data(self):
        if self.socket and self.socket.state() == QBluetoothSocket.ConnectedState:
            txt = self.send_input.text()
            if txt:
                self.socket.write(txt.encode())
                self.data_edit.append(f'发送: {txt}')
                self.send_input.clear()

    @Slot()
    def _on_connected(self):
        self.status_lbl.setText('蓝牙状态: 已连接')
        self.conn_btn.setEnabled(False)
        self.disconn_btn.setEnabled(True)
        self.send_input.setEnabled(True)
        self.send_btn.setEnabled(True)
        self.data_edit.append('=== 蓝牙连接成功 ===')

    @Slot()
    def _on_disconnected(self):
        self.status_lbl.setText('蓝牙状态: 已断开')
        self.conn_btn.setEnabled(True)
        self.disconn_btn.setEnabled(False)
        self.send_input.setEnabled(False)
        self.send_btn.setEnabled(False)
        self.data_edit.append('=== 蓝牙连接断开 ===')

    @Slot(QBluetoothSocket.SocketError)
    def _on_error(self, err):
        self.status_lbl.setText(f'蓝牙错误: {err.name}')
        self.data_edit.append(f'连接错误: {err.name}')

    # ========== 新增的 _on_ready_read 方法 ==========
    @Slot()
    def _on_ready_read(self):
        """读取蓝牙接收到的数据"""
        if not self.socket:
            return
        
        try:
            # 读取所有可用数据
            while self.socket.bytesAvailable() > 0:
                # 方法1: 读取所有数据
                data = self.socket.readAll()
                received_text = data.data().decode('utf-8', errors='ignore')
                
                # 方法2: 如果需要按行读取，可以使用下面的代码
                # if self.socket.canReadLine():
                #     data = self.socket.readLine()
                #     received_text = data.data().decode('utf-8', errors='ignore').strip()
                # else:
                #     # 如果没有完整的一行，可以累积数据
                #     return
                
                if received_text.strip():
                    # 在UI中显示接收到的数据
                    self.data_edit.append(f'接收: {received_text.strip()}')
                    
                    # 自动滚动到底部
                    scrollbar = self.data_edit.verticalScrollBar()
                    scrollbar.setValue(scrollbar.maximum())
                    
                    # 可以在这里添加数据处理逻辑
                    self._process_received_data(received_text.strip())
                if len(received_text.strip()) != 0:
                    self.r_data_singal.emit(received_text.strip())
                    
        except Exception as e:
            self.data_edit.append(f'读取数据错误: {str(e)}')

    def _process_received_data(self, data):
        """处理接收到的数据（可根据需要扩展）"""
        # 示例：根据数据内容执行不同操作
        try:
            # 如果是JSON格式数据
            if data.startswith('{') and data.endswith('}'):
                # 可以解析JSON数据
                pass
            
            # 如果是命令数据
            elif data.startswith('CMD:'):
                command = data[4:].strip()
                self._handle_command(command)
            
            # 如果是传感器数据
            elif '温度' in data or '湿度' in data:
                self._handle_sensor_data(data)
                
        except Exception as e:
            print(f"处理数据时出错: {e}")

    def _handle_command(self, command):
        """处理接收到的命令"""
        self.data_edit.append(f'执行命令: {command}')
        # 在这里添加命令处理逻辑

    def _handle_sensor_data(self, data):
        """处理传感器数据"""
        self.data_edit.append(f'传感器数据: {data}')
        # 在这里添加传感器数据处理逻辑





